package com.ruifu.act.utils;

import org.activiti.bpmn.model.*;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.task.Task;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ActivityCommonUtil {

    /**
     * 根据流程实例id获取上一个节点的信息
     *
     * @param proInsId
     * @param historyService
     * @return
     */
    public static HistoricTaskInstance queryUpOneNodeMessage(String proInsId, HistoryService historyService) {
        //上一个节点
        List<HistoricTaskInstance> list = historyService
                .createHistoricTaskInstanceQuery()
                .processInstanceId(proInsId)
                .orderByHistoricTaskInstanceEndTime()
                .desc()
                .list();
        HistoricTaskInstance taskInstance = null;
        if (!list.isEmpty()) {
            if (list.get(0).getEndTime() != null) {
                taskInstance = list.get(0);
            }
        }
        return taskInstance;
    }

    /**
     * 根据任务id获取上一个节点的信息
     *
     * @param taskId
     * @return
     */
    public static HistoricTaskInstance queryUpOneNode(String taskId, HistoryService historyService) {
        //上一个节点
        List<HistoricTaskInstance> list = historyService
                .createHistoricTaskInstanceQuery()
                .taskId(taskId).orderByHistoricTaskInstanceEndTime()
                .desc()
                .list();
        HistoricTaskInstance taskInstance = null;
        if (!list.isEmpty()) {
            if (list.get(0).getEndTime() != null) {
                taskInstance = list.get(0);
            }
        }
        return taskInstance;
    }

    /**
     * 获取下一节点信息
     *
     * @param task
     * @param flag
     * @return
     */
    public static List<String> nextTaskName(Task task, String flag, RepositoryService repositoryService) {
        List<String> nameList = new ArrayList<>();
        HashMap<String, Object> vars = new HashMap<>();
        vars.put("message", flag);
        //根据流程定义id获取bpmnModel对象
        BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
        //获取当前节点信息
        FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(task.getTaskDefinitionKey());
        //获取当前节点输出连线
        List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();
        //遍历输出连线
        for (SequenceFlow outgoingFlow : outgoingFlows) {
            //获取输出节点元素
            FlowElement targetFlowElement = outgoingFlow.getTargetFlowElement();
            //排除非用户任务接点
            if (targetFlowElement instanceof UserTask) {
                //判断输出节点的el表达式
                if (isCondition(outgoingFlow.getConditionExpression(), vars)) {
                    //true 获取输出节点名称
                    nameList.add(outgoingFlow.getTargetFlowElement().getName());
                }
            }
        }
        return nameList;
    }

    /**
     * el表达式判断
     *
     * @param expression
     * @param vars
     * @return
     */
    private static boolean isCondition(String expression, Map<String, Object> vars) {
        if (expression == null || expression == "") {
            return false;
        }

        //分割表达式
        String[] exprArr = expression.split("[{}$&]");
        for (String expr : exprArr) {
            //是否包含键message
            if (expr.contains("message")) {
                if (!vars.containsKey("message")) {
                    continue;
                }
                if (expr.contains("==")) {
                    String[] primes = expr.split("==");
                    String valExpr = primes[1].trim();
                    if (valExpr.startsWith("'")) {
                        valExpr = valExpr.substring(1);
                    }
                    if (valExpr.endsWith("'")) {
                        valExpr = valExpr.substring(0, valExpr.length() - 1);
                    }
                    if (primes.length == 2 && valExpr.equals(vars.get("message"))) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}
